﻿#include <iostream>
//条款7：为多态基类声明虚析构函数

//记录时间的方法很多，合理的做法是创建一个基类，并未不同的计时方法创建派生类
class TimeKeeper
{
public:
    TimeKeeper()
    {
        std::cout << "TimeKeeper()" << std::endl;
    } //允许派生类使用默认构造函数
    virtual ~TimeKeeper()
    {
        std::cout << "~TimeKeeper()" << std::endl;
    } //允许派生类使用析构函数
};

class AtomicClock : public TimeKeeper
{
public:
    AtomicClock()
    {
        std::cout << "AtomicClock()" << std::endl;
    } //允许派生类使用默认构造函数
    ~AtomicClock()
    {
        std::cout << "~AtomicClock()" << std::endl;
    } //允许派生类使用析构函数
};
class WaterClock : public TimeKeeper
{
public:
    WaterClock()
    {
        std::cout << "WaterClock()" << std::endl;
    } //允许派生类使用默认构造函数
    ~WaterClock()
    {
        std::cout << "~WaterClock()" << std::endl;
    } //允许派生类使用析构函数
};
TimeKeeper* getTimeKeeper(int kind)
{
    switch (kind)
    {
    case 1:
        return new AtomicClock(); //返回一个指向基类的指针，指向派生类对象
    case 2:
        return new WaterClock(); //返回一个指向基类的指针，指向派生类对象
    default:
        break;
    }
};
//当一个类不打算成为基类时，将析构函设为虚函数通常不是一个好主意
class Point
{
public:
    Point(int x, int y) : x_(x), y_(y)
    {
        std::cout << "Point()" << std::endl;
    } //允许派生类使用默认构造函数
    ~Point()
    {
        std::cout << "~Point()" << std::endl;
    } //允许派生类使用析构函数
private:
    int x_;
    int y_;
};
//如果int占用32位，Point对象通常可以装入64位的寄存器中，并可以作为64位的数据传递给其他语言编写的函数，如C或Fortran
//使用虚函数需要额外的，名为vptr的指针，vptr指向一个函数指针数组，称为vtbl


//如果你想创造一个抽象类，但却没有任何纯虚函数。怎么办
class AWOV
{
public:
    virtual ~AWOV() = 0;//声明纯虚析构函数
};
AWOV::~AWOV() //必须提供纯虚析构函数的定义
{
    std::cout << "~AWOV()" << std::endl;
} //允许派生类使用析构函数
void item7()
{
    TimeKeeper* p = getTimeKeeper(1); //返回一个指向基类的指针，指向派生类对象
    delete p; //析构函数调用顺序：先调用派生类的析构函数，再调用基类的析构函数
}

//多态基类应该声明虚析构函数。如果一个类有虚函数，它应该有一个虚析构函数。
//非基类或非多态使用的类不应该声明虚析构函数。